1 package org.apache.maven.surefire.junitcore;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.surefire.booter.Command;
23 import org.apache.maven.surefire.booter.CommandListener;
24 import org.apache.maven.surefire.booter.CommandReader;
25 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
26 import org.apache.maven.surefire.common.junit4.JUnitTestFailureListener;
27 import org.apache.maven.surefire.common.junit4.Notifier;
28 import org.apache.maven.surefire.common.junit48.FilterFactory;
29 import org.apache.maven.surefire.common.junit48.JUnit48Reflector;
30 import org.apache.maven.surefire.common.junit48.JUnit48TestChecker;
31 import org.apache.maven.surefire.providerapi.AbstractProvider;
32 import org.apache.maven.surefire.providerapi.ProviderParameters;
33 import org.apache.maven.surefire.report.ConsoleLogger;
34 import org.apache.maven.surefire.report.ReporterFactory;
35 import org.apache.maven.surefire.suite.RunResult;
36 import org.apache.maven.surefire.testset.TestListResolver;
37 import org.apache.maven.surefire.testset.TestSetFailedException;
38 import org.apache.maven.surefire.util.RunOrderCalculator;
39 import org.apache.maven.surefire.util.ScanResult;
40 import org.apache.maven.surefire.util.ScannerFilter;
41 import org.apache.maven.surefire.util.TestsToRun;
42 import org.junit.runner.manipulation.Filter;
43 import org.junit.runner.notification.Failure;
44 import org.junit.runner.notification.RunListener;
45
46 import java.util.Collection;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Set;
50 import java.util.concurrent.ConcurrentHashMap;
51
52 import static java.util.Collections.unmodifiableCollection;
53 import static org.apache.maven.surefire.booter.CommandReader.getReader;
54 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTests;
55 import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
56 import static org.apache.maven.surefire.common.junit4.Notifier.pureNotifier;
57 import static org.apache.maven.surefire.junitcore.ConcurrentRunListener.createInstance;
58 import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
59 import static org.apache.maven.surefire.testset.TestListResolver.optionallyWildcardFilter;
60 import static org.apache.maven.surefire.util.TestsToRun.fromClass;
61
62
63
64
65 @SuppressWarnings( { "UnusedDeclaration" } )
66 public class JUnitCoreProvider
67 extends AbstractProvider
68 {
69 private final ClassLoader testClassLoader;
70
71 private final JUnitCoreParameters jUnitCoreParameters;
72
73 private final ScannerFilter scannerFilter;
74
75 private final Collection<RunListener> customRunListeners;
76
77 private final ProviderParameters providerParameters;
78
79 private final ScanResult scanResult;
80
81 private final int rerunFailingTestsCount;
82
83 private final JUnit48Reflector jUnit48Reflector;
84
85 private final RunOrderCalculator runOrderCalculator;
86
87 private final TestListResolver testResolver;
88
89 private final CommandReader commandsReader;
90
91 private TestsToRun testsToRun;
92
93 public JUnitCoreProvider( ProviderParameters bootParams )
94 {
95
96 commandsReader = bootParams.isInsideFork() ? getReader().setShutdown( bootParams.getShutdown() ) : null;
97 providerParameters = bootParams;
98 testClassLoader = bootParams.getTestClassLoader();
99 scanResult = bootParams.getScanResult();
100 runOrderCalculator = bootParams.getRunOrderCalculator();
101 jUnitCoreParameters = new JUnitCoreParameters( bootParams.getProviderProperties() );
102 scannerFilter = new JUnit48TestChecker( testClassLoader );
103 testResolver = bootParams.getTestRequest().getTestListResolver();
104 rerunFailingTestsCount = bootParams.getTestRequest().getRerunFailingTestsCount();
105 String listeners = bootParams.getProviderProperties().get( "listener" );
106 customRunListeners = unmodifiableCollection( createCustomListeners( listeners ) );
107 jUnit48Reflector = new JUnit48Reflector( testClassLoader );
108 }
109
110 public Iterable<Class<?>> getSuites()
111 {
112 testsToRun = scanClassPath();
113 return testsToRun;
114 }
115
116 private boolean isSingleThreaded()
117 {
118 return jUnitCoreParameters.isNoThreading();
119 }
120
121 public RunResult invoke( Object forkTestSet )
122 throws TestSetFailedException
123 {
124 final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
125
126 final RunResult runResult;
127
128 final ConsoleLogger consoleLogger = providerParameters.getConsoleLogger();
129
130 Filter filter = jUnit48Reflector.isJUnit48Available() ? createJUnit48Filter() : null;
131
132 Notifier notifier =
133 new Notifier( createRunListener( reporterFactory, consoleLogger ), getSkipAfterFailureCount() );
134
135
136 if ( testsToRun == null )
137 {
138 setTestsToRun( forkTestSet );
139 }
140
141
142 JUnitTestFailureListener testFailureListener = new JUnitTestFailureListener();
143 notifier.addListener( testFailureListener );
144
145 if ( isFailFast() && commandsReader != null )
146 {
147 registerPleaseStopJUnitListener( notifier );
148 }
149
150 try
151 {
152 JUnitCoreWrapper core = new JUnitCoreWrapper( notifier, jUnitCoreParameters, consoleLogger );
153
154 if ( commandsReader != null )
155 {
156 registerShutdownListener( testsToRun );
157 commandsReader.awaitStarted();
158 }
159
160 notifier.asFailFast( isFailFast() );
161 core.execute( testsToRun, customRunListeners, filter );
162 notifier.asFailFast( false );
163
164
165 if ( isRerunFailingTests() )
166 {
167 Notifier rerunNotifier = pureNotifier();
168 notifier.copyListenersTo( rerunNotifier );
169 JUnitCoreWrapper rerunCore = new JUnitCoreWrapper( rerunNotifier, jUnitCoreParameters, consoleLogger );
170 for ( int i = 0; i < rerunFailingTestsCount && !testFailureListener.getAllFailures().isEmpty(); i++ )
171 {
172 List<Failure> failures = testFailureListener.getAllFailures();
173 Map<Class<?>, Set<String>> failingTests = generateFailingTests( failures, testClassLoader );
174 testFailureListener.reset();
175 FilterFactory filterFactory = new FilterFactory( testClassLoader );
176 Filter failingMethodsFilter = filterFactory.createFailingMethodFilter( failingTests );
177 rerunCore.execute( testsToRun, failingMethodsFilter );
178 }
179 }
180 }
181 finally
182 {
183 runResult = reporterFactory.close();
184 notifier.removeListeners();
185 }
186 return runResult;
187 }
188
189 private void setTestsToRun( Object forkTestSet )
190 throws TestSetFailedException
191 {
192 if ( forkTestSet instanceof TestsToRun )
193 {
194 testsToRun = (TestsToRun) forkTestSet;
195 }
196 else if ( forkTestSet instanceof Class )
197 {
198 Class<?> theClass = (Class<?>) forkTestSet;
199 testsToRun = fromClass( theClass );
200 }
201 else
202 {
203 testsToRun = scanClassPath();
204 }
205 }
206
207 private boolean isRerunFailingTests()
208 {
209 return rerunFailingTestsCount > 0;
210 }
211
212 private boolean isFailFast()
213 {
214 return providerParameters.getSkipAfterFailureCount() > 0;
215 }
216
217 private int getSkipAfterFailureCount()
218 {
219 return isFailFast() ? providerParameters.getSkipAfterFailureCount() : 0;
220 }
221
222 private void registerShutdownListener( final TestsToRun testsToRun )
223 {
224 commandsReader.addShutdownListener( new CommandListener()
225 {
226 public void update( Command command )
227 {
228 testsToRun.markTestSetFinished();
229 }
230 } );
231 }
232
233 private void registerPleaseStopJUnitListener( final Notifier stoppable )
234 {
235 commandsReader.addSkipNextTestsListener( new CommandListener()
236 {
237 public void update( Command command )
238 {
239 stoppable.pleaseStop();
240 }
241 } );
242 }
243
244 private JUnit4RunListener createRunListener( ReporterFactory reporterFactory, ConsoleLogger consoleLogger )
245 throws TestSetFailedException
246 {
247 if ( isSingleThreaded() )
248 {
249 NonConcurrentRunListener rm = new NonConcurrentRunListener( reporterFactory.createReporter() );
250 startCapture( rm );
251 return rm;
252 }
253 else
254 {
255 final Map<String, TestSet> testSetMap = new ConcurrentHashMap<String, TestSet>();
256
257 ConcurrentRunListener listener = createInstance( testSetMap, reporterFactory, isParallelTypes(),
258 isParallelMethodsAndTypes(), consoleLogger );
259 startCapture( listener );
260
261 return new JUnitCoreRunListener( listener, testSetMap );
262 }
263 }
264
265 private boolean isParallelMethodsAndTypes()
266 {
267 return jUnitCoreParameters.isParallelMethods() && isParallelTypes();
268 }
269
270 private boolean isParallelTypes()
271 {
272 return jUnitCoreParameters.isParallelClasses() || jUnitCoreParameters.isParallelSuites();
273 }
274
275 private Filter createJUnit48Filter()
276 {
277 final FilterFactory factory = new FilterFactory( testClassLoader );
278 Map<String, String> props = providerParameters.getProviderProperties();
279 Filter groupFilter = factory.canCreateGroupFilter( props ) ? factory.createGroupFilter( props ) : null;
280 TestListResolver methodFilter = optionallyWildcardFilter( testResolver );
281 boolean onlyGroups = methodFilter.isEmpty() || methodFilter.isWildcard();
282 if ( onlyGroups )
283 {
284 return groupFilter;
285 }
286 else
287 {
288 Filter jUnitMethodFilter = factory.createMethodFilter( methodFilter );
289 return groupFilter == null ? jUnitMethodFilter : factory.and( groupFilter, jUnitMethodFilter );
290 }
291 }
292
293 private TestsToRun scanClassPath()
294 {
295 TestsToRun scanned = scanResult.applyFilter( scannerFilter, testClassLoader );
296 return runOrderCalculator.orderTestClasses( scanned );
297 }
298 }